package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.help.StageAverageStayTimeHelp;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.domain.entity.ext.PaasAttachmentEntityExt;
import com.xbongbong.paas.help.StageDetailHelp;
import com.xbongbong.paas.model.StageProcessModel;
import com.xbongbong.paas.pojo.CommentPojo;
import com.xbongbong.paas.service.PaasCommentService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.businesstage.pojo.StageLogPojo;
import com.xbongbong.pro.businesstage.pojo.WorkFinishPojo;
import com.xbongbong.pro.detailtab.dto.DetailTabDataGetDTO;
import com.xbongbong.pro.detailtab.pojo.HistoryStagePojo;
import com.xbongbong.pro.detailtab.vo.HistoryStageVO;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.saas.domain.entity.OpportunityStageLogEntity;
import com.xbongbong.saas.domain.entity.OpportunityWorkLogEntity;
import com.xbongbong.saas.domain.entity.SaleStageEntity;
import com.xbongbong.saas.domain.entity.StageWorkEntity;
import com.xbongbong.saas.domain.entity.ext.OpportunityEntityExt;
import com.xbongbong.saas.enums.BusinessCommentEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.model.OpportunityModel;
import com.xbongbong.saas.model.OpportunityStageLogModel;
import com.xbongbong.saas.model.OpportunityWorkLogModel;
import com.xbongbong.saas.model.SaleStageModel;
import com.xbongbong.saas.model.StageWorkModel;
import com.xbongbong.saas.service.OpportunityStageLogService;
import com.xbongbong.sys.model.UserModel;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author haibin.zhang
 * @version v1.0
 * @date 2019/3/14 19:05
 * @since v1.0
 */
@Service("opportunityStageLogService")
public class OpportunityStageLogServiceImpl implements OpportunityStageLogService {

    @Resource
    private OpportunityModel opportunityModel;
    @Resource
    private OpportunityStageLogModel opportunityStageLogModel;
    @Resource
    private SaleStageModel saleStageModel;
    @Resource
    private PaasCommentService paasCommentService;
    @Resource
    private OpportunityWorkLogModel opportunityWorkLogModel;
    @Resource
    private StageWorkModel stageWorkModel;
    @Resource
    private UserModel userModel;
    @Resource
    private StageProcessModel stageProcessModel;
    @Resource
    private StageAverageStayTimeHelp stageAverageStayTimeHelp;

    @Override
    public HistoryStageVO getHistoryStage(DetailTabDataGetDTO detailTabDataGetDTO) throws XbbException {
        HistoryStageVO historyStageVO = new HistoryStageVO();
        String corpid = detailTabDataGetDTO.getCorpid();
        Long opportunityId = detailTabDataGetDTO.getDataId();
        OpportunityEntityExt opportunity = opportunityModel.getByKey(opportunityId,corpid);
        Long formId = opportunity.getFormId();

        Map<String,Object> modelMap = new HashMap<>(16);

        String nowStageCode = opportunity.getData().getString(SalesOpportunityEnum.SALE_STAGE.getAttr());
        Long stageProcessId = opportunity.getData().getLong(SalesOpportunityEnum.STAGE_PROCESS_ID.getAttr());
        if (StringUtil.isEmpty(nowStageCode)) {
            return historyStageVO;
        }
        //老数据重新查询stageProcessId
        Integer stageUnit;
        if (Objects.isNull(stageProcessId) && StringUtil.isNotEmpty(nowStageCode)) {
            modelMap.put("corpid", corpid);
            modelMap.put("formId", formId);
            modelMap.put("del", 0);
            modelMap.put("oldTransferVersion", 1);
            List<StageProcessEntity> stageProcessEntityList = stageProcessModel.findEntitys(modelMap);
            if (CollectionsUtil.isEmpty(stageProcessEntityList)) {
                return historyStageVO;
            }
            stageProcessId = stageProcessEntityList.get(0).getId();
            stageUnit = stageProcessEntityList.get(0).getStageUnit();
        }else {
            StageProcessEntity stageProcessEntity = stageProcessModel.getByKey(stageProcessId, corpid);
            stageUnit = stageProcessEntity.getStageUnit();
        }

        // 当前阶段未被启用直接返回空
        modelMap.put("corpid", corpid);
        modelMap.put("formId", formId);
        modelMap.put("stageProcessId",stageProcessId);
        modelMap.put("code",nowStageCode);
        modelMap.put("enable",1);
        modelMap.put("del", 0);
        List<SaleStageEntity> list = saleStageModel.findEntitys(modelMap);
        if (CollectionsUtil.isEmpty(list)){
            return historyStageVO;
        }

        //按顺序获取版本下的所有阶段
        modelMap.clear();
        modelMap.put("corpid",corpid);
        modelMap.put("del",0);
        modelMap.put("stageProcessId",stageProcessId);
        modelMap.put("enable",1);
        modelMap.put("formId",formId);
        modelMap.put("orderByStr","sort desc");
        modelMap.put("columns","code,name,type");
        List<SaleStageEntity> saleStageEntityList = saleStageModel.findEntitys(modelMap);

        //按进入时间获得版本下的所有阶段执行记录
        modelMap.clear();
        modelMap.put("corpid",corpid);
        modelMap.put("dataId",opportunityId);
        modelMap.put("del",0);
        modelMap.put("stageProcessId",stageProcessId);
        //客户阶段记录根据数据字典中的顺序排序
        modelMap.put("orderByStr","into_time desc");
        List<OpportunityStageLogEntity> opportunityStageLogEntityList = opportunityStageLogModel.findEntitys(modelMap);

        /*
         * 排除由于阶段排序后，未完成阶段展示历史阶段的问题
         * 因为要求按时间倒序排列，从找到当前记录开始读取数据
         * 如果历史阶段顺序与数据字典不同，不管！
         * */
        boolean catchNowStage = false;
        //key:阶段code,阶段名
        Map<String,String> stageNameMap = new HashMap<>(16);
        //阶段idList
        List<String> opportunityStageCodeList = new ArrayList<>();
        //开启工作阶段idList
        List<String> openWorkStageCodeList = new ArrayList<>();
        for (SaleStageEntity entity : saleStageEntityList){
            String code = entity.getCode();
            stageNameMap.put(code,entity.getName());
            openWorkStageCodeList.add(code);
            if (!catchNowStage){
                opportunityStageCodeList.add(code);
            }
            if (Objects.equals(code,nowStageCode)){
                catchNowStage = true;
            }
        }
        List<String> stageCodeIn = new ArrayList<>();
        List<Long> stageLogIdIn = new ArrayList<>();
        //key:阶段记录id,value:阶段记录
        Map<String,OpportunityStageLogEntity> stageLogMap = new HashMap<>(16);
        Map<Long,String> codeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (OpportunityStageLogEntity entity : opportunityStageLogEntityList){
            if (opportunityStageCodeList.contains(entity.getStageCode()) && !Objects.equals(entity.getStageCode(),nowStageCode)){
                stageCodeIn.add(entity.getStageCode());
                stageLogIdIn.add(entity.getId());
                stageLogMap.put(entity.getStageCode(),entity);
                codeMap.put(entity.getId(),entity.getStageCode());
            }
        }
        //已完成且开启阶段工作的阶段
        stageCodeIn.retainAll(openWorkStageCodeList);
        Map<String,List<WorkFinishPojo>> workMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (!stageCodeIn.isEmpty()){
            workMap = getWorkArray(stageCodeIn,stageLogIdIn,corpid,opportunity.getFormId(),stageProcessId);
        }
        Map<String,List<CommentPojo>> commentMap = paasCommentService.getStageComment(stageLogIdIn,corpid,codeMap,BusinessCommentEnum.SALE_STAGE.getCode(),detailTabDataGetDTO);

        List<HistoryStagePojo> historyStagePojoList = new ArrayList<>();
        for (String stageCode : stageCodeIn){
            HistoryStagePojo historyStagePojo = new HistoryStagePojo();
            historyStagePojo.setWorkArray(workMap.getOrDefault(stageCode,new ArrayList<>()));
            historyStagePojo.setCommentArray(commentMap.getOrDefault(stageCode,new ArrayList<>()));
            OpportunityStageLogEntity entity = stageLogMap.get(stageCode);
            Long intoTime = entity.getIntoTime();
            Long outTime = entity.getOutTime();
            StageLogPojo stageLogPojo = new StageLogPojo();
            stageLogPojo.setName(stageNameMap.get(entity.getStageCode()));
            stageLogPojo.setIntoTime(DateTimeUtil.getStringEpochSecond(intoTime));
            stageLogPojo.setOutTime(DateTimeUtil.getStringEpochSecond(outTime));
            long l = outTime - intoTime;
            stageLogPojo.setStayTime(stageAverageStayTimeHelp.secondToTime(l, stageUnit));
            stageLogPojo.setRefId(entity.getId());
            historyStagePojo.setNowStage(stageLogPojo);
            historyStagePojoList.add(historyStagePojo);
        }
        historyStageVO.setHistoryList(historyStagePojoList);
        return historyStageVO;
    }

    private Map<String,List<WorkFinishPojo>> getWorkArray(List<String> stageCodeIn, List<Long> stageLogIdIn, String corpid, Long formId,Long stageProcessId) {
        Map<String,Object> modelMap = new HashMap<>(16);
        modelMap.put("corpid",corpid);
        modelMap.put("stageLogIdIn",stageLogIdIn);
        modelMap.put("del",0);
        List<OpportunityWorkLogEntity> opportunityWorkLogEntityList = opportunityWorkLogModel.findEntitys(modelMap);
        //ley:工作id,value:阶段工作
        Map<Long,OpportunityWorkLogEntity> workLogMap = new HashMap<>(16);
        //员工idList
        List<String> userIdList = new ArrayList<>();
        for (OpportunityWorkLogEntity entity : opportunityWorkLogEntityList){
            workLogMap.put(entity.getStageWorkId(),entity);
            userIdList.add(entity.getUserId());
        }

        //员工名map
        Map<String,String> userMap = userModel.getUserIdNameMap(corpid,userIdList);

        modelMap.clear();
        modelMap.put("corpid",corpid);
        modelMap.put("businessType",XbbRefTypeEnum.SALE_STAGE.getCode());
        modelMap.put("saasMark", SaasMarkEnum.SAAS.getCode());
        modelMap.put("formId",formId);
        modelMap.put("stageProcessId",stageProcessId);
        modelMap.put("del",0);
        modelMap.put("orderByStr","sort desc");
        List<StageWorkEntity> stageWorkEntityList = stageWorkModel.findEntitys(modelMap);
        Map<String,List<WorkFinishPojo>> workFinishMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (StageWorkEntity entity : stageWorkEntityList){
            Long workId = entity.getId();
            OpportunityWorkLogEntity workLog = workLogMap.getOrDefault(workId,new OpportunityWorkLogEntity());
            if (!stageCodeIn.contains(entity.getStageCode())){
                continue;
            }
            WorkFinishPojo workFinishPojo = new WorkFinishPojo();
            workFinishPojo.setId(workId);
            workFinishPojo.setName(entity.getName());
            workFinishPojo.setIsRequired(entity.getRequired());
            Integer isFinished = workLog.getIsFinished();
            Boolean bool = isFinished == null ? false : isFinished == 1;
            workFinishPojo.setIsFinished(bool);
            workFinishPojo.setUserName(userMap.get(workLog.getUserId()));
            if (bool){
                workFinishPojo.setFinishedTime(DateTimeUtil.getStringEpochSecond(workLog.getFinishedTime()));
            }
            workFinishPojo.setProportion(entity.getProportion());
            JSONObject executionEvent = entity.getExecutionEvent();
            if (Objects.nonNull(executionEvent)){
                workFinishPojo.setExecutionEventType(executionEvent.getInteger("type"));
            }
            if (Objects.nonNull(executionEvent)){
                workFinishPojo.setExecutionEventName(executionEvent.getString("name"));
            }
            workFinishPojo.setEditable(0);
            workFinishPojo.setDescription(entity.getDescription());

            workFinishPojo.setImages(StageDetailHelp.getImageHtmlList(workLog.getImage()));
            String attachment = workLog.getAttachment();
            if (StringUtil.isEmpty(attachment)) {
                workFinishPojo.setAttachments(new ArrayList<>());
            } else {
                workFinishPojo.setAttachments(JSONArray.parseArray(attachment, PaasAttachmentEntityExt.class));
            }
            List<WorkFinishPojo> workFinishPojoList = workFinishMap.getOrDefault(entity.getStageCode(),new ArrayList<>());
            workFinishPojoList.add(workFinishPojo);
            workFinishMap.put(entity.getStageCode(),workFinishPojoList);
        }
        return workFinishMap;
    }

}
